#include "../Include/QueryBuilder.hpp"

using Supetronix::PersistO::DL::QueryBuilder;

const string Supetronix::PersistO::DL::QueryBuilder::WhereParamTag = "@Fil";

string QueryBuilder::BuildWhereClause(const QueryModifierBase* queryModifier)
{
	//query modifier will have the list of all the parameters required for the query
	shared_ptr<vector<ParameterInfo>> filterData = queryModifier->getParameterList();	

	//using the string stream to help with string operations like "integer" value concatenation etc
	stringstream whereClause;
	stringstream paramName;
	int index = 1;

	if ( !filterData->empty() )
	{
		//filterData->begin()->ParameterName;
		//build the where clause part of the SQL
		for( auto& filter : *filterData )
		{
			//filter.ParamFilterType;

			//adding the index to param tag to make it unique in the query and then assign the parameter name to query modifer so it can be used later for building the 
			//where clause
			paramName << WhereParamTag << index++;
			filter.ParameterName = paramName.str();

			//building the where clause with column name, sql query filter keyword and the generated parameter name
			whereClause << filter.ColumnName << SqlFilterString(filter.ParamFilterType) << filter.ParameterName << std::endl;
		}
	}

	return whereClause.str();
}


string QueryBuilder::SqlFilterString(FilterType& queryFilterType)
{
	//convert the filter type enum to specific SQL filter keywords
	switch (queryFilterType)
	{
	case Supetronix::PersistO::Common::FilterType::IsNull:
		return " IS NULL ";
	case Supetronix::PersistO::Common::FilterType::In:
		return " IN ";
	case Supetronix::PersistO::Common::FilterType::Between:
		return " BETWEEN ";
	case Supetronix::PersistO::Common::FilterType::Equal:
		return " = ";
	case Supetronix::PersistO::Common::FilterType::NotEqual:
		return " <> ";
	case Supetronix::PersistO::Common::FilterType::IsNotNull:
		return " IS NOT NULL ";
	case Supetronix::PersistO::Common::FilterType::GreaterThan:
		return " > ";
	case Supetronix::PersistO::Common::FilterType::GreaterThanEqual:
		return " >= ";
	case Supetronix::PersistO::Common::FilterType::LessThan:
		return " < ";
	case Supetronix::PersistO::Common::FilterType::LessThanEqual:
		return " <= ";
	}
}

void QueryBuilder::TransformQueryParameters(string& query, const ConnectionSourceType& connectionType)
{
    if ( !query.empty() )
    {
        if ( connectionType == ConnectionSourceType::MySQL )
        {
			//replace the "@" query where param tags with provider specific tags using the C++11 regex class
            //std::regex pattern ("(\\Q@\\E)\\w+\\b", std::regex_constants::icase | std::regex_constants::syntax_option_type::perl);
            std::regex pattern ("[\\@]\\w+\\b", std::regex_constants::icase);
            string replace = "?";

            query = std::regex_replace( query, pattern, replace);
        }
    }
}